home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
plan
/
src
/
weekcalc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
8KB
|
269 lines
/*
* Arrange entries in the week view.
*
* build_week() Build the week node trees for all days
* of the week beginning on curr_week.
* destroy_week() Release the week node trees.
*/
#include <time.h>
#include <Xm/Xm.h>
#include "cal.h"
#define NDAYS 7 /* # of days in a week view */
extern struct tm *time_to_tm();
extern BOOL lookup_entry(), lookup_next_entry();
extern char *mknotestring();
extern struct config config; /* global configuration data */
extern struct list *mainlist; /* list of all schedule entries */
extern struct user *user; /* user list (from file_r.c) */
extern int nusers; /* number of users in user list */
extern XFontStruct *font[NFONTS]; /* fonts: FONT_* */
extern int curr_year; /* year being displayed, since 1900 */
time_t curr_week; /* week being displayed, time in sec */
struct week week; /* info on week view */
/*
* given the first day of a week, build the data structures that describe
* all entries in the display. Before calling this routine, set week_curr
* to 0:00 of the first day of the week.
*/
static BOOL add_week_entry();
build_week()
{
struct config *c = &config;
time_t date; /* midnight of calculated day */
int wday; /* day counter, 0..NDAYS-1 */
int nlines=0; /* total number of bar lines */
struct tm *tm; /* check if wday in same year*/
struct list *list; /* current list: mainlist or user's */
int u; /* user counter, -1 == ourselves */
struct entry *ep; /* ptr to entry in mainlist */
BOOL found; /* TRUE if lookup succeeded */
struct lookup lookup; /* result of entry lookup */
struct weeknode *wp; /* for counting # of lines on a day */
if (!c->week_maxhour) c->week_maxhour = 20;
destroy_week();
update_user_lists();
curr_week = date = curr_week - curr_week % 86400;
for (wday=0; wday < NDAYS; wday++, date+=86400) {
week.nlines[wday] = 0;
tm = time_to_tm(date);
if (tm->tm_year != curr_year)
continue;
for (u= -1; u < nusers; u++) {
if (u != -1 && (user[u].suspended || !user[u].list))
continue;
list = u == -1 ? mainlist : user[u].list,
found = lookup_entry(&lookup, list, date, TRUE, FALSE);
for (; found; found = lookup_next_entry(&lookup)) {
if (lookup.trigger >= date + 86400)
break;
ep = &list->entry[lookup.index];
if (ep->note && *ep->note == '-')
continue;
if (!add_week_entry(wday, lookup.trigger,
&list->entry[lookup.index],
u == -1 ? 0 : &user[u])) {
destroy_week();
return;
}
}
}
for (wp=week.tree[wday]; wp; wp=wp->down)
week.nlines[wday]++;
if (!week.nlines[wday])
week.nlines[wday] = 1;
nlines += week.nlines[wday];
}
week.canvas_xs = c->week_margin
+ c->week_daywidth
+ c->week_gap
+ c->week_hourwidth *
(c->week_maxhour - c->week_minhour)
+ c->week_margin;
week.canvas_ys = c->week_margin
+ c->week_title
+ c->week_margin
+ c->week_hour
+ NDAYS * c->week_gap
+ nlines * (c->week_barheight + 2*c->week_bargap)
+ c->week_gap
+ c->week_margin;
}
/*
* insert an entry into the tree for week day <wday>. Try to find a hole
* in an existing line, or append a new line if no hole can be found. This
* routine is used by build_week() only.
*/
#define GET_EXTENT(node, ep, begin, end) \
{ \
begin = !config.weekwarn ? node->trigger \
: ep->early_warn > ep->late_warn \
? node->trigger - ep->early_warn \
: node->trigger - ep->late_warn; \
end = ep->notime ? node->trigger + config.week_minhour * 3600 \
: node->trigger + ep->length; \
if (!node->textinside) \
end += (node->textlen+6) * 3600/config.week_hourwidth; \
}
static BOOL add_week_entry(wday, time, new, userp)
int wday; /* day counter, 0..NDAYS-1 */
time_t time; /* appropriate trigger time */
struct entry *new; /* entry to insert */
struct user *userp; /* which user owns entry? */
{
struct weeknode *node; /* new week struct */
struct weeknode *vert; /* for finding free line */
struct weeknode *horz; /* for finding free slot */
struct entry *old; /* already inserted entry */
time_t new_begin, new_end; /* extent of entry to insert */
time_t old_begin, old_end; /* extent of existing entry */
#ifdef JAPAN
int i, clen = 0, plen = 0;
strpack partialstr[MAXPARTIALSTRING];
unsigned char strpool[MAXPARTIALCHAR];
#endif
if (!(node = (struct weeknode *)malloc(sizeof(struct weeknode))))
return(FALSE);
node->next = node->prev = node->up = node->down = 0;
node->entry = new;
node->user = userp;
node->trigger = time;
node->text[0] = 0;
if (config.weekuser && userp && userp->name)
sprintf(node->text, "(%.20s) ", userp->name);
strncat(node->text, mknotestring(new),
sizeof(node->text)-1-strlen(node->text));
node->text[sizeof(node->text)-1] = 0;
#ifdef JAPAN
partialstr->strptr = strpool;
if ((node->textlen = mixedstrlen_in_pixels(node->text, partialstr,
FONT_WNOTE, FONT_JNOTE)) >
config.week_maxnote) {
for (i=0; partialstr[i].strptr != NULL &&
i < MAXPARTIALSTRING ||
((node->textlen = plen), 0); i++) {
if (plen + partialstr[i].pixlen > config.week_maxnote){
/* Truncating*/
partialstr[i].length *=
(double)(config.week_maxnote-plen) /
(double)partialstr[i].pixlen;
node->textlen = config.week_maxnote;
if (partialstr[i].length == 0 ||
partialstr[i].asciistr == False &&
(partialstr[i].length &= ~1) == 0)
partialstr[i].strptr = NULL;
node->text[clen += partialstr[i].length] ='\0';
break;
} else {
clen += partialstr[i].length;
plen += partialstr[i].pixlen;
}
}
}
#else
truncate_string(node->text, config.week_maxnote, FONT_WNOTE);
node->textlen = strlen_in_pixels(node->text, FONT_WNOTE);
#endif
node->textinside = new->length * config.week_hourwidth / 3600 -
config.week_barheight > node->textlen;
if (!week.tree[wday]) {
week.tree[wday] = node;
return(TRUE);
}
GET_EXTENT(node, new, new_begin, new_end);
for (vert=week.tree[wday]; vert; vert=vert->down) {
old = vert->entry;
GET_EXTENT(vert, old, old_begin, old_end);
if (new_end <= old_begin) { /* first in line? */
node->up = vert->up;
node->down = vert->down;
node->next = vert;
vert->prev = node;
return(TRUE);
}
for (horz=vert; horz; horz=horz->next) {
if (new_begin < old_end)
break;
if (!horz->next) { /* last in line? */
node->prev = horz;
horz->next = node;
return(TRUE);
}
old = horz->next->entry;
GET_EXTENT(horz->next, old, old_begin, old_end);
if (new_end <= old_begin) { /* fits in hole? */
node->next = horz->next;
node->prev = horz;
horz->next->prev = node;
horz->next = node;
return(TRUE);
}
}
if (!vert->down) { /* append new line? */
vert->down = node;
node->up = vert;
return(TRUE);
}
}
return(FALSE); /* we never get here */
}
/*
* destroy the week trees for all days.
*/
destroy_week()
{
int wday; /* day counter */
struct weeknode *vert, *nextvert; /* line pointer */
struct weeknode *horz, *nexthorz; /* node pointer */
for (wday=0; wday < NDAYS; wday++) {
for (vert=week.tree[wday]; vert; vert=nextvert) {
nextvert = vert->down;
for (horz=vert; horz; horz=nexthorz) {
nexthorz = horz->next;
free((void *)horz);
}
}
week.tree[wday] = 0;
}
}
/*
* return the length of <string> in pixels.
*/
strlen_in_pixels(string, sfont)
register unsigned char *string; /* string to truncate */
int sfont; /* FONT_* */
{
register int len; /* length in pixels */
for (len=0; *string; string++)
len += font[sfont]->per_char
[*string - font[sfont]->min_char_or_byte2].width;
return(len);
}